﻿// rtsp_player.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <conio.h>
#include <thread>
#include <chrono>
#include "../librtsp/librtsp.h"
#include "../third_party/opencv/opencv2/opencv.hpp"
#include "../third_party/opencv/opencv2/core/core.hpp"
#include "../third_party/opencv/opencv2/imgproc/imgproc.hpp"
#include "../third_party/opencv/opencv2/highgui/highgui.hpp"
#include "../third_party/opencv/opencv2/imgproc/imgproc_c.h"

#ifdef _WIN64
#pragma comment(lib, "../x64/librtsp.lib")
#pragma comment(lib, "../third_party/opencv/lib/x64/opencv_world490.lib")

#else

#pragma comment(lib, "../../bin/librtsp.lib")

#endif // !WIN32	


int gStart = true;
void encode_data(void* handle,void* data,int len,int w,int h,int type)
{
    cv::Mat src(h, w, CV_8UC3, (uchar*)data);
    cvtColor(src, src, CV_RGB2BGR);
    char szName[64] = { 0 };
    sprintf(szName, "%p", handle);
    cv::namedWindow(szName, 0);
    imshow(szName, src);
    cv::waitKey(1);
    //Sleep(2);
}


void fun(void* handle)
{
    long long s = GetTickCount64();
    while (gStart)
    {
        char* data = nullptr;
        int len = 0;
        int w = 0;
        int h = 0;
        int type = -1;
        int i = 0;
        auto beg_time = std::chrono::high_resolution_clock::now();
        int ret = rtsp_getframe_ex(handle, &data, &len, &w, &h,&type);
        if (ret == 0)
        {
            if (type)
            {
                cv::Mat src1(h + h / 2, w, CV_8UC1, (uchar*)data);
                cv::Mat dst1(h, w, CV_8UC3);
                cvtColor(src1, dst1, CV_YUV2BGR_I420);
                char szName[64] = { 0 };
                sprintf(szName, "%p", handle);
                cv::namedWindow(szName, 0);
                cv::imshow(szName, dst1);
            }
            else
            {
                //cv::Mat src(h, w, CV_8UC3, (uchar*)data);
                //cvtColor(src, src, CV_RGB2BGR);
                //char szName[64] = { 0 };
                //sprintf(szName, "%p", handle);
                //cv::namedWindow(szName, 0);
                //imshow(szName, src);
                //cv::waitKey(1);
            }
            //printf("%p\n", data);
        }
        else
        {
            printf("%d\n", ret);
        }
        auto end_time = std::chrono::high_resolution_clock::now();
        long long duration_num = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - beg_time).count();
       // printf(" get %lld ms ", duration_num);

    }
    fprintf(stderr," funend\n ");
}

void audio_fun_(void* handle, void* data, int len)
{
}

int main()
{
    rtsp_hw_support(0);
    rtsp_enable_console_log();
    rtsp_init();
    std::vector<std::string> uris;
    //uris.push_back("rtsp://admin:Admin12345@192.168.7.111:554/video2");
    //uris.push_back("rtsp://admin:able1234@192.168.7.104:554/stream1");
    uris.push_back("rtsp://admin:able123456@192.168.50.120:554/stream1");
    //uris.push_back("rtsp://127.0.0.1/live/4k60fps_hevc");
    //uris.push_back("rtsp://admin:Admin12345@192.168.50.135:554/stream1");
    //uris.push_back("rtsp://admin:Admin12345@192.168.50.51:554/stream1");
    //uris.push_back("rtsp://admin:Admin12345@192.168.50.52:554/stream1");
    //uris.push_back("rtsp://admin:Admin12345@192.168.50.53:554/stream1");
    //uris.push_back("rtsp://admin:Admin12345@192.168.50.54:554/stream1");
    if (__argc >= 2)
    {
        uris.clear();
        uris.push_back(*(__argv + 1));
    }
    std::vector<void*> rets;
    std::vector<std::thread> allThread;
    for (size_t i = 0; i < uris.size(); i++)
    {
        void* handle = rtsp_generate(uris[i].c_str());
        rtsp_set_audio_cb(handle, audio_fun_);
        rtsp_start(handle);
        allThread.emplace_back(std::thread(&fun, handle));
        rets.push_back(handle);
    };
    int i=0;
    while (true)
    {
        char s = getch();
        if ('q'==tolower(s))
        {
            gStart = false;
            break;
        }
    }
    for (auto handle : rets)
    {
        rtsp_stop(handle);
    }
    for (auto& thread:allThread)
    {
        if (thread.joinable())
        {
            thread.join();
        }
    }
    for (auto handle : rets)
    {
        rtsp_release(&handle);
    }
    std::cout << "Hello World!\n";
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
